본 게시글의 원문은 Yann Debray의 MATLAB with Python Book 입니다. 해당 책은 MIT 라이센스를 따르기 때문에 개인적으로 번역하여 재배포 합니다. 본 포스팅에는 추후 유료 수익을 위한 광고가 부착될 수도 있습니다.

MIT License

Copyright (c) 2023 Yann Debray

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

본 게시물에서 활용된 소스 코드들은 모두 Yann Debray의 GitHub Repo에서 확인할 수 있습니다.

4.4. MATLAB에서 Python 사용자 정의 함수 호출하기

이 장에서는 동료인 Ian McKenna가 개발한 데모를 활용할 것입니다. 그는 MathWorks에서 금융 분야의 주요 응용 엔지니어로 근무하며, 기업 웹 예측 분석을 구축하고 다른 비즈니스 중요 응용 프로그램이 웹 서비스로 연결될 수 있도록 담당하고 있습니다. 이 예시는 2장에서의 날씨 예시와 동일한 구조를 따릅니다.

이 웹 서비스는 암호화폐의 가격을 예측하는 것을 목표로 합니다:

다음과 같은 형식의 데이터(JSON)를 반환합니다.

[{"Time":"2022-01-21T12:00:00Z","predictedPrice":2466.17},
...
{"Time":"2022-01-21T17:00:00Z","predictedPrice":2442.25}]

첫 번째 단계는 특정 암호화폐의 가격 변동을 간단히 보여주는 애플리케이션을 개발하는 것입니다:

A picture containing diagram Description automatically generated

이를 통해 지난 24시간 동안의 가격 변화를 모니터링하고 이에 기반해 암호화폐 자산을 사거나 판매하는 결정을 내릴 수 있습니다. 그런데 어느 날, 매니저가 다가와 다음과 같이 말합니다:

“이봐, 좋은 아이디어가 있는데. 만약 우리가 과거 데이터가 아닌 예측 데이터에 접근할 수 있다면, 예측이 100% 정확하더라도 현재로서는 얻는 이익 이상의 추가 수익을 얻을 수 있을거야.”

기관에는 MATLAB 전문 지식을 가진 몇 명의 퀀트(quants) 연구원이 있다고 가정해 봅시다. 그리고 그들은 비즈니스 사용자가 찾는 예측 모델을 구축하는 방법을 정확히 알고 있습니다.

하지만 그에 앞서, 우리의 첫 번째 과제는 Python 데이터 스크래핑 라이브러리를 호출하고 해당 데이터를 직접 MATLAB으로 가져오는 것입니다. 우선 손쉽게 해당하는 암호화폐 URL을 구문 분석하고 도메인 이름만 추출하는 작업을 해보겠습니다. 이를 위해 urllib 패키지의 하위 모듈인 parseurlparse 함수를 사용하려고 합니다.

startDate = '2022-01-21T12:00:00Z';
stopDate = '2022-01-21T17:00:00Z';
url = "https://api.pro.coinbase.com/products/ETH-USD/candles?start="+startDate+"&end="+stopDate+"&granularity=60"
url = "https://api.pro.coinbase.com/products/ETH-USD/candles?start=2022-01-21T12:00:00Z&end=2022-01-21T17:00:00Z&granularity=60"
urlparts = py.urllib.parse.urlparse(url)
urlparts = 
  Python ParseResult with properties:

    fragment
    hostname
    netloc
    params
    password
    path
    port
    query
    scheme
    username

    ParseResult(scheme='https', netloc='api.pro.coinbase.com', path='/products/ETH-USD/candles', params='', query='start=2022-01-21T12:00:00Z&end=2022-01-21T17:00:00Z&granularity=60', fragment='')

domain = urlparts.netloc
domain = 
  Python str with no properties.

    api.pro.coinbase.com

MATLAB과 Python 간의 중간 데이터 이동을 최소화하기 위해, 몇 가지 함수를 포함하는 Python 사용자 정의 모듈dataLib.py를 작성합니다.

jsonData = py.dataLib.getPriceData("ETH", startDate, stopDate)
data = py.dataLib.parseJson(jsonData, [0,4])

dataLib.pyCoinbase Pro에서 1분봉(1-minute bars)을 가져옵니다. API는 시작 날짜로 지정한 첫 번째 분을 가져오지 않으므로 시간 범위는 (시작, 끝]입니다. 데이터 반환에는 Numpy 배열부터 목록 및 딕셔너리 및 JSON까지 다양한 데이터 구조를 사용합니다.

이것이 MATLAB에서 이 함수를 호출하는 방법입니다.

참고: dataLib.py는 Python의 경로에 있어야 합니다.

product = "ETH";
product = "ETH"
startDate = '2022-01-21T12:00:00Z';
stopDate = '2022-01-21T17:00:00Z';
jsonData = py.dataLib.getPriceData(product, startDate, stopDate);

만약 Live Script에 상호작용성을 추가하고 싶다면, Live Controls라는 이름의 요소를 추가할 수 있습니다. 이는 매개변수나 옵션을 제공하여 사용자가 Live Script 내에서 조절할 수 있도록 하여 상호작용성과 시나리오 분석을 향상시킵니다.

리본에서 컨트롤을 삽입할 수 있습니다:

이것이 Live Control을 매개변수화하는 방법입니다:

여기에서 유용한 또 다른 유형의 Live Control은 parseJson 함수에서 반환할 정보를 선택하는 간단한 체크박스입니다:

여기에서 유용한 또 다른 유형의 Live Control은 parseJson 함수에서 반환할 정보를 선택하는 간단한 체크박스입니다:

Dates = true;
Low = false;
High = false;
Open = false;
Close = true;
Volume = false;

% Python 인덱싱(0부터 시작)에 맞게 1을 뺍니다
selectedColumns = find([Dates Low High Open Close Volume])-1;
selectedColumns = 1x2    
     0     4

Python 인덱싱이 0부터 시작하기 때문에 결과 배열에서 1을 빼는 것에 주의하세요.

% this function returns back two outputs as a tuple
data = py.dataLib.parseJson(jsonData, selectedColumns);

우리 이야기의 이 부분에서 마지막으로 할 일은 Python 함수 출력을 MATLAB 데이터 유형으로 변환하는 것입니다 (이는 Python과 MATLAB 간 데이터 매핑에 대한 이 장의 마지막 부분에서 다룰 예정입니다).

priceData = data{1};
priceData = 
  Python ndarray:

   1.0e+09 *

    1.6428    0.0000
    1.6428    0.0000
    ...
    1.6428    0.0000
    1.6428    0.0000

    Use details function to view the properties of the Python object.

    Use double function to convert to a MATLAB array.

Python 객체의 속성을 보려면 details 함수를 사용하세요.

MATLAB 배열로 변환하려면 double 함수를 사용하세요.

columnNames = data{2}
columnNames = 
  Python list with no properties.

    ['Date', 'Close']

그런 다음 우리는 오른쪽의 Numpy 배열을 단순히 double 명령을 사용하여 캐스팅할 수 있습니다:

priceData = double(priceData);
priceData = 300x2    
1.0e+09 *

    1.6428    0.0000
    1.6428    0.0000
    1.6428    0.0000
    1.6428    0.0000
    1.6428    0.0000
    1.6428    0.0000
    1.6428    0.0000
    1.6428    0.0000
    1.6428    0.0000
    1.6428    0.0000

마찬가지로 문자열(또는 R2022a 이전 버전에서는 cell)과 같은 목록을 캐스팅하기 위한 다양한 명령이 있습니다:

columnNames = string(columnNames);

우리가 MATLAB에서 이러한 데이터를 가지고 있는 경우, MATLAB 테이블로 변환하게 되는데, 이는 기본적으로 Pandas 데이터 프레임과 유사합니다:

data = array2table(priceData, 'VariableNames', columnNames);

테이블과 마찬가지로, 타임테이블은 간단한 유형의 작업이나 복잡한 유형의 작업을 수행하기 위해 몇 년 동안 MATLAB에 내장된 데이터 구조입니다. 만약 시간대를 다루고, 시간을 세계 표준 시간대에 따른 시간으로 변환하고 싶다면, datetime 명령을 사용하여 해당 변환을 수행할 수 있습니다.

data.Date = datetime(data.Date, 'ConvertFrom', 'posixtime', 'TimeZone', 'America/New_York')
  Date Close
1 21-Jan-2022 12:00:00 2.8073e+03
2 21-Jan-2022 11:59:00 2.8108e+03
3 21-Jan-2022 11:58:00 2.8051e+03
4 21-Jan-2022 11:57:00 2.8071e+03
5 21-Jan-2022 11:56:00 2.8051e+03
6 21-Jan-2022 11:55:00 2.8028e+03
7 21-Jan-2022 11:54:00 2.7984e+03
8 21-Jan-2022 11:53:00 2.7983e+03
9 21-Jan-2022 11:52:00 2.8062e+03
10 21-Jan-2022 11:51:00 2.8054e+03
11 21-Jan-2022 11:50:00 2.8061e+03
12 21-Jan-2022 11:49:00 2.8012e+03
13 21-Jan-2022 11:48:00 2.8008e+03
14 21-Jan-2022 11:47:00 2.8030e+03
plot(data.Date, data.Close)

사용자 정의 Python 모듈 다시 로드하기

만약 dataLib 모듈 내부의 함수들을 수정했다면 어떻게 해야 할까요? MATLAB에서 해당 함수들을 다시 호출하겠지만 어떤 차이도 보이지 않을 것입니다. 이는 모듈을 다시 로드해야 하기 때문입니다:

mod = py.importlib.import_module('dataLib');
py.importlib.reload(mod);

때때로 모듈을 언로드해야 할 수도 있는데, 이를 위해 클래스를 지워야 합니다. 이렇게 하면 MATLAB 작업 공간에서 모든 변수, 스크립트, 클래스가 삭제됩니다.

clear classes 

Python을 프로세스 외부에서 실행하고 있다면, 다른 접근 방법으로는 프로세스를 종료하는 것입니다.

terminate(pyenv)